
#include <string.h>
#include "fun.h"
#include "Debug.h"
#include "BSP.h"
//	#include "Driver.h"
#include "BSP_Timer.h"
#include "Timer.h"
#include "log/log2.h"
#include "FreeRTOS.h"
#include "atomic.h"
#include "Task.h"
#include "Timers.h"
#include "version.h"
#include "task_config.h"
#include "semphr.h"
#include "stream_buffer.h"

#include "SimpleTag.h"

#include "id_card2.h"
#include "HIDProx.h"


#define LF_PRESENT_COUNT		50

//事件标识
#define LF_EVENT_DATA			(1u << 0)		//ISR接收到数据标识
#define LF_EVENT_START		(1u << 1)		//启动标识
#define LF_EVENT_STOP		(1u << 2)		//停止标识
#define LF_EVENT_OK			(1u << 3)			//读卡成功标识
//读卡事件标识
#define LF_EVENT_POLL (LF_EVENT_DATA | LF_EVENT_START | LF_EVENT_STOP)


typedef enum {
	LF_S_IDLE,		//空闲
	LF_S_POLLING,	//寻卡中	
}LF_State_T;

typedef struct {
	StreamBufferHandle_t hStreamBuffer;
	EventGroupHandle_t hEvent;
	TimerHandle_t hTimer;
	uint32_t flag;		//读卡标识
	SimpleTag_T tag;	//读卡结果
	int8_t poll_time;	//读卡等待时间
	int8_t read_count;	//读卡有效次数
	int8_t present_count;	//卡在场
	LF_State_T state;	//状态
	uint8_t uid_buf[5];
} reader_lf_t;

static reader_lf_t reader_lf = {
	.hStreamBuffer = NULL,
	.hEvent = NULL,
	.tag = {0},
	.poll_time = -1,
	.read_count = 0,
	.state = LF_S_IDLE,
};


void rf_data_input_isr(uint16_t *data, uint16_t len)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	size_t size = len * 2;
	size_t ret = xStreamBufferSendFromISR(reader_lf.hStreamBuffer, data, size, &xHigherPriorityTaskWoken);
	if(ret != size){
		LOG2_ERR("send error: %d", ret);
	}
	//设置数据事件
	xEventGroupSetBitsFromISR(reader_lf.hEvent, LF_EVENT_DATA, &xHigherPriorityTaskWoken);
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

static void Reader_LF_Tick( TimerHandle_t xTimer ){
	if(reader_lf.poll_time > 0){
		reader_lf.poll_time--;
	}
	if(reader_lf.present_count > 0){
		reader_lf.present_count--;
	}
}


void Reader_LF_Init(void){
	reader_lf.hEvent = xEventGroupCreate();
	reader_lf.hStreamBuffer = xStreamBufferCreate(1024, 1);
	reader_lf.hTimer = xTimerCreate("lf", pdMS_TO_TICKS(10), pdTRUE, NULL, Reader_LF_Tick);
	xTimerStart(reader_lf.hTimer, portMAX_DELAY);
	HIDProx_Init();
	id_card_reset();
}

void Reader_LF_RfOff(void){	
	//触发停止事件
	xEventGroupSetBits(reader_lf.hEvent, LF_EVENT_STOP);
}
//检测当前标签类型是否与读卡标识一致
static int reader_lf_check_tag_type(SimpleTag_T* tag, uint32_t flag){
	if(flag & RFID_ITF_TAG_ID && tag->type == LFTAG_EM4102){
		return 1;
	}
	if(flag & RFID_ITF_TAG_HID && tag->type == LFTAG_HIDPROX){
		return 1;
	}
	return 0;
}


//读卡
int Reader_LF_Read(uint32_t flag, SimpleTag_T* tag){

	if((flag & RFID_ITF_TAG_ID) && !(reader_lf.flag & RFID_ITF_TAG_ID)){		
		id_card_reset();		
	}

	if((flag & RFID_ITF_TAG_HID) && !(reader_lf.flag & RFID_ITF_TAG_HID)){
		HIDProx_Reset();
	}

	reader_lf.flag = flag;
	
	if(reader_lf.state == LF_S_IDLE){
		//触发启动
		xEventGroupSetBits(reader_lf.hEvent, LF_EVENT_START);
	}
	//检测标签状态是否有效，有效则返回成功
	if(reader_lf.present_count > 0 && reader_lf.read_count > 0){
		if(reader_lf_check_tag_type(&reader_lf.tag, flag)){
			reader_lf.read_count--;
			reader_lf.poll_time = 20;
			xEventGroupWaitBits(
						reader_lf.hEvent,    // The event group being tested.
						LF_EVENT_OK,  // The bits within the event group to wait for.
						pdTRUE,         // BITs should be cleared before returning.
						pdFALSE,        // Don't wait for both bits, either bit will do.
						0 ); // Wait a maximum of 100ms for either bit to be set.	
			vTaskDelay(10);					
			//进入临界区			
			taskENTER_CRITICAL();
			*tag = reader_lf.tag;
			//推出临界区
			taskEXIT_CRITICAL();
			return 0;
		}
		LOG2_WRN("LF tag type dismatch");
		reader_lf.read_count = 0;
		reader_lf.present_count = -1;
	}

	EventBits_t uxBits;
	TickType_t xTicksToWait;

	if(reader_lf.present_count > 0){
		xTicksToWait = 70 / portTICK_PERIOD_MS;
	}
	else{
		xTicksToWait = 200 / portTICK_PERIOD_MS;
	}
	vTaskDelay(10);
	uxBits = xEventGroupWaitBits(
				reader_lf.hEvent,    // The event group being tested.
				LF_EVENT_OK,  // The bits within the event group to wait for.
				pdTRUE,         // BITs should be cleared before returning.
				pdFALSE,        // Don't wait for both bits, either bit will do.
				xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
	if(uxBits & LF_EVENT_OK){
		//进入临界区			
		taskENTER_CRITICAL();
		*tag = reader_lf.tag;
		//推出临界区
		taskEXIT_CRITICAL();
		return 0;
	}
	return -1;
}

//读HID Prox卡
static int reader_lf_proc_hidprox(SimpleTag_T *tag, uint16_t* data, uint16_t len){ 
	int ret;
	HidProxTag_T info;
	info.type = 0xFF;
	HIDProxDecoder_Input(data, len);
	ret = HIDProx_Read(&info);
	if(ret == 0){
		uint8_t uid_len = (info.type + 7) / 8;
		uint8_t uid_bit = info.type;
		SimpleTag_Set(tag, LFTAG_HIDPROX, uid_bit, uid_len, info.uid);
	}
	
	return ret;	
}

/*------------------------------------------------------ */
static void reader_id_clear_uid(reader_lf_t* reader){
	memset(reader->uid_buf, 0, sizeof(reader->uid_buf));
}

// static int reader_id_is_invalid_uid(uint8_t* uid){
// 	static const uint8_t invalid_uid[5] = {0x00};
// 	if(memcmp(invalid_uid, uid, 5) == 0){
// 		return 1;
// 	}
// 	return 0;
// }

static int reader_id_check_update(reader_lf_t* reader, uint8_t* uid){
	if(memcmp(uid, reader->uid_buf, 5)){
		memcpy(reader->uid_buf, uid, 5);
		return 0;
	}
	else{
		return 1;
	}
}
//读ID卡
static int reader_lf_proc_idcard(reader_lf_t* reader, SimpleTag_T *tag, uint16_t* data, uint16_t len){ 
	uint8_t uid[5];
	int ret;
	ret = id_card_data_decode3(data, len);
	ret = id_card_get(uid);
	if(ret < 0){
		return ret;
	}

	if(!reader_id_check_update(reader, uid)){
		//第一次读到卡
		return 1;
	}

	uint8_t uid_len = 5;
	uint8_t uid_bit = uid_len * 8;
	SimpleTag_Set(tag, LFTAG_EM4102, uid_bit, uid_len, uid);
	reader_id_clear_uid(reader);
	
	return 0;
}

static int reader_lf_proc_data(reader_lf_t *reader, SimpleTag_T *tag, uint16_t* data, uint16_t len){
	int ret = -1;
	//读HID Prox
	if(reader->flag & RFID_ITF_TAG_HID){
		ret = reader_lf_proc_hidprox(tag, data, len);
		if(ret >= 0){
			return ret;
		}
	}
	if(reader->flag & RFID_ITF_TAG_ID){
		ret = reader_lf_proc_idcard(reader, tag, data, len);
	}
	return ret;
}

int Reader_LF_Service(void){
	int ret;
	SimpleTag_T tag;
	//等待事件触发
	EventBits_t uxBits;
	const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;

     uxBits = xEventGroupWaitBits(
                 reader_lf.hEvent,    // The event group being tested.
                 LF_EVENT_POLL,  // The bits within the event group to wait for.
                 pdTRUE,         // BITs should be cleared before returning.
                 pdFALSE,        // Don't wait for both bits, either bit will do.
                 xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.

     if( ( uxBits & LF_EVENT_START ) != 0 ){
        //启动读卡
		reader_lf.state = LF_S_POLLING;
		reader_lf.present_count = 0;
		reader_lf.read_count = 0;
		reader_lf.poll_time = 25;
		HIDProx_Reset();
		id_card_reset();
		reader_id_clear_uid(&reader_lf);
		BSP_RFID_Enable();
		bsp_lf_adc_phase(672);
		LOG2_INF("LF_EVENT_START");
     }
	 else
     if( ( uxBits & LF_EVENT_STOP ) != 0 ){
         //停止读卡
		BSP_RFID_Disable();
		reader_lf.poll_time = -1;
		reader_lf.read_count = 0;
		reader_lf.present_count = 0;
		reader_lf.state = LF_S_IDLE;
		memset(&reader_lf.tag, 0, sizeof(reader_lf.tag));
		LOG2_INF("LF_EVENT_STOP");
     }

	static uint16_t data[128];
	while(1){
		size_t rlen = xStreamBufferReceive(reader_lf.hStreamBuffer, data, sizeof(data), 0);
		if(!rlen){
			break;
		}
		if(reader_lf.state == LF_S_POLLING){
			ret = reader_lf_proc_data(&reader_lf, &tag, data, rlen/2);
			if(!ret){
				reader_lf.tag = tag;
				reader_lf.present_count = LF_PRESENT_COUNT;
				reader_lf.poll_time = 20;
				reader_lf.read_count = 2;
				//触发读卡OK事件
				xEventGroupSetBits(reader_lf.hEvent, LF_EVENT_OK);
				LOG2_INF("LF OK");
			}
			else
			if(ret > 0 
				&& reader_lf.present_count > 0
				&& reader_lf.poll_time > 0){
				//有卡，但是读卡错误
				reader_lf.poll_time = 20;
				reader_lf.read_count = 2;
				xEventGroupSetBits(reader_lf.hEvent, LF_EVENT_OK);
				LOG2_INF("LF Keep");
			}
		}
	}

	if(reader_lf.poll_time == 0){
		//读卡超时
		BSP_RFID_Disable();
		reader_lf.poll_time = -1;
		reader_lf.read_count = 0;
		reader_lf.present_count = 0;
		reader_lf.state = LF_S_IDLE;
		memset(&reader_lf.tag, 0, sizeof(reader_lf.tag));
		LOG2_INF("Poll end");
	}

	return 0;
}


